package io.renren.modules.testrestful.service.impl;

//import cn.hutool.json.JSONObject;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
//import io.renren.modules.alarmonline.service.WebSocketService;
import io.renren.modules.alarmonline.service.WebSocketService;
import io.renren.modules.cuttingmachinehisdata.dao.CuttingmachineHisdataDao;
import io.renren.modules.cuttingmachinehisdata.entity.CuttinghisEntity;
import io.renren.modules.testrestful.dao.DevicePropertiesDao;
import io.renren.modules.testrestful.dao.DriverResDao;
import io.renren.modules.testrestful.dao.UsersDao;
import io.renren.modules.testrestful.entity.DevicesInfoResponse;
import io.renren.modules.testrestful.entity.DriverResPojo;
import io.renren.modules.testrestful.entity.SendWs;
import io.renren.modules.testrestful.entity.User;
import io.renren.modules.testrestful.service.FontWebSocketService;
import io.renren.modules.testrestful.service.UsersService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.socket.*;
import org.springframework.web.socket.client.WebSocketConnectionManager;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@EnableScheduling
@Service("usersService")
public class UsersServiceImpl extends ServiceImpl<UsersDao,User> implements  UsersService {
    @Autowired
    UsersDao usersDao;
    @Autowired
    DriverResDao driverResDao;

    @Autowired
    WebSocketService webSocketService;

    @Autowired
    FontWebSocketService fontWebSocketService;

    @Autowired

    CuttingmachineHisdataDao cuttingmachineHisdataDao;

    @Override
    public User getUsers(String id) {
        return usersDao.getUsers(id);
    }

    @Override
    public List<User> getUsersList() {
        return usersDao.getUsersList();
    }

    @Override
    public int postUsers(User users) {
        return usersDao.postUsers(users);
    }

    @Override
    public String putUsers(String id, User users) {
        return usersDao.putUsers(id,users);
    }

    @Override
    public String deleteUsers(String id) {
        return usersDao.deleteUsers(id);
    }




    @Data
    public static class  ReHeader{
        private String username;
        private String  password;
    }

    @Autowired
    private RestTemplate restTemplate;
    //    @Scheduled(cron = "0/5 * * * * ?")
    public Object getToken(){
        RestTemplate restTemplate = new RestTemplate();

        // 获取token
        ReHeader reHeader = new ReHeader();
//        reHeader.setUsername("test@thingsboard.com");
//        reHeader.setPassword("Test!@#123456");
//        String url = "https://thingsboardtest.cmhijs.cn/api/auth/login";


        reHeader.setUsername("716_api@thingsboard.com");
        reHeader.setPassword("716Api@2024");
        String url = "https://thingsboard.cmhijs.cn:8443/api/auth/login";
        String token = restTemplate.postForObject(url,reHeader, String.class);
        JSONObject jsonObject = JSONObject.parseObject(token);
        String token1 = jsonObject.getString("token");
        return token1.toString();
    }

    @Data
    public static class  A {

        private B tsSubCmds;
    }
    @Data
    public static class  B {
        private String type;
    }
    //获取设备信息
    @Async("screenTaskExecutor")
//    @Scheduled(cron = "0/10 * * * * ?")
    public String getDevicesInfo() throws InterruptedException {
        log.info("切割机线程-" + Thread.currentThread().getId() + "正在执行");
        HttpHeaders headers = new HttpHeaders();

//        String url= "https://thingsboard.cmhijs.cn:8443/api/customer/52a9aac0-c949-11ed-826f-2d2aeab65199/deviceInfos?pageSize=10&page=0&sortProperty=createdTime&sortOrder=DESC&deviceProfileId=87564350-1eb7-11ee-9e2f-eba35a8e94c4";
        String url= "https://thingsboard.cmhijs.cn:8443/api/customer/52a9aac0-c949-11ed-826f-2d2aeab65199/deviceInfos?pageSize=10&page=0&sortProperty=createdTime&sortOrder=DESC&deviceProfileId=87564350-1eb7-11ee-9e2f-eba35a8e94c4";

        RestTemplate restTemplate = new RestTemplate();

        String token=getToken().toString();
        String val = "Bearer " + token;

        headers.set("x-authorization", val);
        HttpEntity<String> httpEntity = new HttpEntity<>(headers);

        ResponseEntity<DevicesInfoResponse> responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity,DevicesInfoResponse.class);
//        System.out.println(responseEntity);
        DevicesInfoResponse dr=responseEntity.getBody();
//        System.out.println(dr);

        List<SendWs> swList = new ArrayList<>(); //创建一个空的swList列表，存储swList对象

        //定义一个映射关系
        Map<Integer,String> cmdIdToDeviceNameMap = new HashMap<>();

        int cmdId = 10;
        for (DevicesInfoResponse.DriverData driverData : dr.getData()) {
//            System.out.println(driverData);//dr.getData:返回一个设备信息列表


            String id = driverData.getId().getId();
//            System.out.println("--------------------------------------------");
//            System.out.println("设备名称："+deviceName+",设备ID："+id+";");

            List<SendWs.TsSubCmds> tsSubCmdList=new ArrayList<>();//创建一个空的tsSubCmdList列表，存储tsSubCmdList对象

            //driverResDao.selectList：查询满足条件的DriverResPojo对象列表，并存储到driverResPojoList中
            List<DriverResPojo> driverResPojoList=driverResDao.selectList(
                    new QueryWrapper<DriverResPojo>().lambda()
                            .eq(DriverResPojo::getDevicename,driverData.getName())
            );
//                System.out.println(driverResPojoList);
            List<String> keysList = new ArrayList<>(); // 初始化 keysList


            for (DriverResPojo driverResPojo : driverResPojoList) {
                keysList.add(driverResPojo.getDevicelabel()); // 将每个 devicelabel 添加到 keysList 中
            }
            if(!keysList.isEmpty()){
                SendWs.TsSubCmds tsSubCmds = new SendWs.TsSubCmds();
                tsSubCmds.setEntityType("DEVICE");
                tsSubCmds.setEntityId(id);
                tsSubCmds.setScope("LATEST_TELEMETRY");
                //  tsSubCmds.setKeys("DDE5.Gruppe_1.AxisPositionX");
//                    tsSubCmds.setKeys(driverResPojo.getDevicelabel());
                tsSubCmds.setKeys(String.join(",", keysList));
                tsSubCmds.setCmdId(cmdId++);
                //存储映射关系
                cmdIdToDeviceNameMap.put(tsSubCmds.getCmdId(), driverData.getName());

                tsSubCmdList.add(tsSubCmds);

                SendWs sendWs = new SendWs();
//            sendWs.setTsSubCmds(tsSubCmdList);
                sendWs.setTsSubCmds(tsSubCmdList);
                sendWs.setHistoryCmds(new ArrayList<>());
                sendWs.setAttrSubCmds(new ArrayList<>());
                swList.add(sendWs);

                System.out.println(sendWs);
                System.out.println("--------------------------------------------");

            }
        }
//            //usersDao.postUsers(usr1);
//
//        }

//        webSocketClientSend(swList,token);
        webSocketClientSend(swList,token,cmdIdToDeviceNameMap);
        return dr.toString();
    }


    // 订阅设备信息
//   @Scheduled(cron = "0/10 * * * * ?")
    public void webSocketClientSend(List<SendWs> swList, String token, Map<Integer, String> cmdIdToDeviceNameMap) throws InterruptedException {

        //  String token = getToken().toString();
        StandardWebSocketClient standardWebSocketClient = new StandardWebSocketClient();
        PrintClientSocketHandler handler= new PrintClientSocketHandler(cmdIdToDeviceNameMap);
        for (SendWs sendWs : swList) {
            handler.setSendString(JSONObject.toJSONString(sendWs));
//            WebSocketConnectionManager webSocketConnectionManager = new WebSocketConnectionManager(
//                    standardWebSocketClient,
//                    handler,
//                    "wss://thingsboardtest.cmhijs.cn/api/ws/plugins/telemetry?" +
//                            "token=" + token,cmdIdToDeviceNameMap);
            WebSocketConnectionManager webSocketConnectionManager = new WebSocketConnectionManager(
                    standardWebSocketClient,
                    handler,
                    "wss://thingsboard.cmhijs.cn:8443/api/ws/plugins/telemetry?" +
                            "token=" + token,cmdIdToDeviceNameMap);


            webSocketConnectionManager.start();

            Thread.sleep(2*1000L);
        }

    }



    public class PrintClientSocketHandler extends AbstractWebSocketHandler {
        private Map<Integer,String> cmdIdToDeviceNameMap = new HashMap<>();//cmd和设备名称的对应关系


        public PrintClientSocketHandler(Map<Integer, String> cmdIdToDeviceNameMap) {
            this.cmdIdToDeviceNameMap = cmdIdToDeviceNameMap;
        }
        // 连接成功,发送信息

        private String sendString=null;
        public void setSendString(String sendString){
            this.sendString=sendString;
        }

        @Override
        public void afterConnectionEstablished(WebSocketSession session) throws Exception {
            log.info("发送 {}",sendString);
            session.sendMessage(new TextMessage(sendString));
        }


//        @Autowired
//        @Autowired
//        private DevicePropertiesDao devicePropertiesDao;

        public Map<String, String> getDevicePropertiesMap() {
            Map<String, String> devicePropertiesMap = new HashMap<>();

            List<DriverResPojo> deviceProperties = driverResDao.selectList(new QueryWrapper<>());

            for (DriverResPojo driverResPojo : deviceProperties) {
                String deviceName = driverResPojo.getDevicename();
                String point = driverResPojo.getDevicelabel();
                String property = driverResPojo.getDeviceprep();

                String key = deviceName + "." + point;
                devicePropertiesMap.put(key, property);
            }

//            System.out.println(devicePropertiesMap);
            return devicePropertiesMap;
        }


        //为每个设备的数据创建一个全局Map。
        private Map<String, Map<String, String>> deviceDataCache = new ConcurrentHashMap<>();

        @Override
//        @Scheduled(cron = "0/5 * * * * ?")
        protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
            String mes=message.getPayload();
            log.info("收到消息：" + message.getPayload());

            JSONObject jsonObject = JSON.parseObject(mes);
            int subscriptionId = jsonObject.getIntValue("subscriptionId");
            String deviceName = cmdIdToDeviceNameMap.get(subscriptionId);
//            log.info("设备名称：" + deviceName);

            JSONObject latestValues = jsonObject.getJSONObject("latestValues");

            Map<String,Object> deviceDataMap = new HashMap<>();//数据和设备名称
//            Map<String, Object> adjustedDeviceDataMap = new HashMap<>();

            for (Map.Entry<String, Object> entry : latestValues.entrySet()) {
                String key = entry.getKey();
                Long latestTimestamp = (Long) entry.getValue();

                //假设 data 中的数组是按照时间戳递增的顺序排列
                JSONArray dataArray = jsonObject.getJSONObject("data").getJSONArray(key);
                for (int i = 0; i < dataArray.size(); i++) {
                    JSONArray itemArray = dataArray.getJSONArray(i);
                    Long timestamp = itemArray.getLong(0);
                    if (timestamp.equals(latestTimestamp)) {
                        Object value = itemArray.get(1);
                        // 存储设备名称和值的映射关系
                        deviceDataMap.put(deviceName + "." + key, value);
                        break;
                    }
                }
//                String key = entry.getKey();
//                Long value = (Long) entry.getValue();
//
//
//                // 将时间戳转换为日期格式
//                Date timestamp = new Date((Long) value);
//                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
//                String formattedTimestamp = dateFormat.format(timestamp);
//
//                // 存储设备名称和值的映射关系
//                deviceDataMap.put(deviceName + "." + key, formattedTimestamp);
            }

            Map<String, String> adjustedDeviceDataMap = new HashMap<>();

            Map<String, String> devicePropertiesMap = getDevicePropertiesMap();

            //遍历deviceDataMap
            for (Map.Entry<String, Object> entry : deviceDataMap.entrySet()) {
                String key = entry.getKey();
                Object value = entry.getValue();

                // 根据devicePropertiesMap调整键的格式
                String adjustedKey = devicePropertiesMap.get(key);
                if (adjustedKey != null) {
                    adjustedDeviceDataMap.put(deviceName + "." + adjustedKey, value.toString());
                }
            }
//            log.info("测试：" + deviceDataMap);
            log.info("调整后的设备数据：" + adjustedDeviceDataMap);

            // 合并数据
            Map<String, String> existingData = deviceDataCache.getOrDefault(deviceName, new HashMap<>());
            existingData.putAll(adjustedDeviceDataMap);  // 如果新数据存在，则替换
            // 旧数据
            deviceDataCache.put(deviceName, existingData);

            String deviceProcessStatus = existingData.getOrDefault(deviceName + ".deviceProcessStatus", "0");
            String deviceMachineSpeed = existingData.getOrDefault(deviceName + ".deviceMachineSpeed", "0");
            String deviceCutStatus = existingData.getOrDefault(deviceName + ".deviceCutStatus", "1");
            String deviceLocation = existingData.getOrDefault(deviceName + ".deviceLocation", "0");
            String deviceStatus = existingData.getOrDefault(deviceName + ".deviceStatus", "0");


//            // 从调整后的设备数据中提取所需字段
//            String deviceProcessStatus = adjustedDeviceDataMap.get(deviceName + ".deviceProcessStatus");
//            String deviceMachineSpeed = adjustedDeviceDataMap.get(deviceName + ".deviceMachineSpeed");
//            String deviceCutStatus = adjustedDeviceDataMap.get(deviceName + ".deviceCutStatus");
//            String deviceLocation = adjustedDeviceDataMap.get(deviceName + ".deviceLocation");
//            String deviceStatus = adjustedDeviceDataMap.get(deviceName + ".deviceStatus");


            // 构建 CuttinginfoEntity 对象
            CuttinghisEntity cuthisEntity = new CuttinghisEntity();
            cuthisEntity.setId(UUID.randomUUID().toString());
            cuthisEntity.setDeviceName(deviceName);
            //
            cuthisEntity.setDeviceProcessStatus(Integer.parseInt(deviceProcessStatus));
            cuthisEntity.setDeviceMachineSpeed(Double.parseDouble(deviceMachineSpeed));
            cuthisEntity.setDeviceCutStatus(Integer.parseInt(deviceCutStatus));
            cuthisEntity.setDeviceLocation(Integer.parseInt(deviceLocation));
            cuthisEntity.setDeviceStatus(Integer.parseInt(deviceStatus));
            cuthisEntity.setTimestamp(LocalDateTime.now());
//             log.info("测试：" + cuthisEntity);

            // 将数据存入数据库
            cuttingmachineHisdataDao.postCutHisData(cuthisEntity);

            // 将调整后的设备数据发送到前端
            String adjustedDeviceDataJson = JSONObject.toJSONString(adjustedDeviceDataMap);
            fontWebSocketService.sendMessage(adjustedDeviceDataJson);
        }

        @Override
        protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception {
//        session.sendMessage(new TextMessage(StandardCharsets.UTF_8.decode(message.getPayload()).toString()));
        }

        @Override
        protected void handlePongMessage(WebSocketSession session, PongMessage message) throws Exception {
            log.info("reconnect...");
            log.info(String.valueOf(new TextMessage(StandardCharsets.UTF_8.decode(message.getPayload()).toString())));
            session.sendMessage(new TextMessage(StandardCharsets.UTF_8.decode(message.getPayload()).toString()));
        }

        @Override
        public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {

        }

        @Override
        public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {

        }

        public void afterConnectionEstablished() {
        }


    }

    public void saveMysql(User user){
        String username = user.getName();
        int count = usersDao.countById(username);
        if(count>0){
            System.out.println("已经存在");
        } else {
            usersDao.postDevices(user);
        }
//        usersDao.postDevices(user);
        log.info("save");
    }


    @Data
    public static class  SaveDevice{
        private String deviceid;
        private String devicename;
    }

}